package com.sagittariusjin.android.serialportbecoroutinelib.client

import android.util.Log
import com.sagittariusjin.android.serialportbecoroutinelib.SerialPortDispatch

import com.sagittariusjin.android.serialportbecoroutinelib.SerialPort
import com.sagittariusjin.android.serialportbecoroutinelib.bean.ResultSerialBean
import com.sagittariusjin.android.serialportbecoroutinelib.bean.SerialBean
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.channels.ReceiveChannel
import java.io.File
import java.lang.Exception


class SerialPortClient constructor(private var address: String, private var baudRate: Int) {

    private var serialPortDispatch: SerialPortDispatch? = null
    private var channelback: ReceiveChannel<ResultSerialBean>? = null
    private var channelsend: Channel<SerialBean>? = null
    private var  serialPort: SerialPort?=null
    var state = false
    private val TAG = "SerialPortClient"
    private var serialNo: Int = -1

    init {
        try {
            serialPort = SerialPort(File(address), baudRate, 0)
            serialPortDispatch = SerialPortDispatch(serialPort)

            serialPortDispatch?.apply {
            channelsend = this.receivechannel
            channelback = this.backchannel
            }
            state = true
        } catch (e: Exception) {
            state =false
            Log.e(TAG, "----串口客户端初始化失败,----error:${e.message}")
        }
    }




    /**
     * 发送数据，并等待数据返回
     *
     * 默认超时时间 2000毫秒
     * @param bean SerialBean
     * @return ResultSerialBean?
     */
    suspend fun getValues(bean: SerialBean): ResultSerialBean? {

        var a = coroutineScope {
            async {

                if (channelsend?.isClosedForSend?:true) {
                    Log.e(TAG, "Send连接断开")
                }
                channelsend?.send(bean)
                serialNo = bean.serialNumber
                if (channelback?.isClosedForReceive?:true) {
                    Log.e(TAG, "Back连接断开")
                    var backDate = channelback?.receive()
                    backDate
                } else {
                    withTimeoutOrNull(2000) {
                        var backDate: ResultSerialBean? = null

                        withTimeoutOrNull(800) {
                            for (resultSerialBean in channelback!!) {
                                backDate = resultSerialBean
                            }
                        }
//                        backDate.serialNumber=serialNo

//                        if (backDate!!.serialNumber!=serialNo){
//                            backDate.code = 500
//                        }

                        backDate
                    }
                }
            }
        }
        var back = a.await()
        serialNo = -1
        return back
    }

    /**
     * 发送数据，并等待数据返回
     *
     *可设置等待时间
     * @param bean SerialBean
     * @param outTime Long 设置超时时间
     * @return ResultSerialBean?
     */
    suspend fun getValues(bean: SerialBean, outTime: Long): ResultSerialBean? {

//        CRCStorytelling.crc16(1, byteArrayOf())

        var a = coroutineScope {
            async {

                if (channelsend?.isClosedForSend?:true) {
                    Log.e(TAG, "Send连接断开")
                }
                channelsend?.send(bean)
                serialNo = bean.serialNumber
                if (channelback?.isClosedForReceive?:true) {
                    Log.e(TAG, "Back连接断开")
                    var backDate = channelback?.receive()
                    backDate
                } else {
                    withTimeoutOrNull(outTime) {
                        var backDate = channelback?.receive()
//                        backDate.serialNumber=serialNo
//                        if (backDate.serialNumber != serialNo) {
//                            backDate.code = 500
//                        }

                        backDate
                    }
                }
            }
        }
        var back = a.await()
        serialNo = -1
        return back
    }

    /**
     * 发送数据，不等待返回值
     *
     *  100 毫秒的等待时间
     * @param bean SerialBean
     * @return ResultSerialBean?
     */
    suspend fun putValues(bean: SerialBean): ResultSerialBean? {


        var a = coroutineScope {
            async {

                if (channelsend?.isClosedForSend?:true) {
                    Log.e(TAG, "Send连接断开")
                }
                channelsend?.send(bean)
                serialNo = bean.serialNumber
                if (channelback?.isClosedForReceive?:true) {
                    Log.e(TAG, "Back连接断开")
                    var backDate = channelback?.receive()
                    backDate
                } else {
                    withTimeoutOrNull(100) {
                        var backDate = channelback?.receive()
//                        backDate.serialNumber=serialNo
//                        if (backDate.serialNumber != serialNo) {
//                            backDate.code = 500
//                        }

                        backDate
                    }
                }
            }
        }
        var back = a.await()
        serialNo = -1
        return back
    }

    fun close() {
        serialPortDispatch?.close()
        serialPort?.close()
        serialPortDispatch = null
        serialPort = null
        channelsend=null
        channelback=null
    }
}